﻿/*
 Wrap Interface of Kinect2 SDK
 According to MS Kinect SDK Vesrion 2.0.1410.19000

 Date : 2014/12/3
 Version : 0.5
 
The MIT License (MIT)

Copyright (c) 2014 DavidWTF

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.ComTypes;

namespace Kinect2
{
    using WAITABLE_HANDLE = System.IntPtr;
    using TIMESPAN = System.Int64;
    using HRESULT = System.UInt32;
    using DWORD = System.UInt32;

    public class IsAvailableChangedEventArgs : BaseEventArgs<IIsAvailableChangedEventArgs>
    {
        public IsAvailableChangedEventArgs() : base() { }
        internal IsAvailableChangedEventArgs(IIsAvailableChangedEventArgs arg) : base(arg) { }
        public bool IsAvailable
        {
            get
            {
                try { return origin.get_IsAvailable(); }
                catch { }
                return false;
            }
        }
    }

    public class KinectSensor : BaseEvent<IKinectSensor, IsAvailableChangedEventArgs>
    {
        public KinectSensor() : base("SubscribeIsAvailableChanged", "UnsubscribeIsAvailableChanged", "GetIsAvailableChangedEventData") { }
        internal KinectSensor(IKinectSensor arg) : base(arg, "SubscribeIsAvailableChanged", "UnsubscribeIsAvailableChanged", "GetIsAvailableChangedEventData") { }

        public static KinectSensor GetDefault()
        {
            IKinectSensor origin = null;
            if (0 == Kinect.GetDefaultKinectSensor(out origin))
                return new KinectSensor(origin);
            return null;
        }
        public void Open() { try { origin.Open(); } catch { } }
        public void Close() { try { origin.Close(); } catch { } }
        public MultiSourceFrameReader OpenMultiSourceFrameReader(FrameSourceTypes enabledFrameSourceTypes)
        {
            try { return new MultiSourceFrameReader(origin.OpenMultiSourceFrameReader((DWORD)enabledFrameSourceTypes)); }
            catch { }
            return null;
        }
        public bool IsOpen
        {
            get { return GetMember<bool>("IsOpen"); }
        }
        public bool IsAvailable
        {
            get { return GetMember<bool>("IsAvailable"); }
        }
        public KinectCapabilities KinectCapabilities
        {
            get { return (KinectCapabilities)GetMember<DWORD>("KinectCapabilities"); }
        }
        public string UniqueKinectId
        {
            get
            {
                try
                {
                    char[] uniqueKinectId = new char[256];
                    origin.get_UniqueKinectId((uint)uniqueKinectId.Length, uniqueKinectId);
                    return new string(uniqueKinectId);
                }
                catch { }
                return null;
            }
        }
        public AudioSource AudioSource
        {
            get { return GetWrappedClass<AudioSource>("AudioSource"); }
        }
        public BodyFrameSource BodyFrameSource
        {
            get { return GetWrappedClass<BodyFrameSource>("BodyFrameSource"); }
        }
        public BodyIndexFrameSource BodyIndexFrameSource
        {
            get { return GetWrappedClass<BodyIndexFrameSource>("BodyIndexFrameSource"); }
        }
        public ColorFrameSource ColorFrameSource
        {
            get { return GetWrappedClass<ColorFrameSource>("ColorFrameSource"); }
        }
        public CoordinateMapper CoordinateMapper
        {
            get { return GetWrappedClass<CoordinateMapper>("CoordinateMapper"); }
        }

        public DepthFrameSource DepthFrameSource
        {
            get { return GetWrappedClass<DepthFrameSource>("DepthFrameSource"); }
        }
        public InfraredFrameSource InfraredFrameSource
        {
            get { return GetWrappedClass<InfraredFrameSource>("InfraredFrameSource"); }
        }
        public LongExposureInfraredFrameSource LongExposureInfraredFrameSource
        {
            get { return GetWrappedClass<LongExposureInfraredFrameSource>("LongExposureInfraredFrameSource"); }
        }
        public event EventHandler<IsAvailableChangedEventArgs> IsAvailableChanged
        {
            add { Add_EventHandler(value); }
            remove { Remove_EventHandler(value); }
        }
    }

    public class KinectBuffer : IDisposable
    {
        IntPtr ptr = IntPtr.Zero;
        uint size = 0;
        public KinectBuffer(IntPtr ptr, uint size)
        {
            this.ptr = ptr;
            this.size = size;
        }
        public uint Size { get { return size; } }
        public IntPtr UnderlyingBuffer { get { return ptr; } }
        public void Dispose()
        {
        }
    }

    public class FrameDescription : BaseInterfaceWrap<IFrameDescription>
    {
        public FrameDescription() : base() { }
        internal FrameDescription(IFrameDescription arg) : base(arg) { }
        public uint BytesPerPixel
        {
            get { return GetMember<uint>("BytesPerPixel"); }
        }
        public uint LengthInPixels
        {
            get { return GetMember<uint>("LengthInPixels"); }
        }
        public float DiagonalFieldOfView
        {
            get { return GetMember<float>("DiagonalFieldOfView"); }
        }
        public float VerticalFieldOfView
        {
            get { return GetMember<float>("VerticalFieldOfView"); }
        }
        public float HorizontalFieldOfView
        {
            get { return GetMember<float>("HorizontalFieldOfView"); }
        }
        public int Height
        {
            get { return GetMember<int>("Height"); }
        }
        public int Width
        {
            get { return GetMember<int>("Width"); }
        }
    }

    public class MultiSourceFrameReference : FrameReference<IMultiSourceFrameReference, MultiSourceFrame>
    {
        public MultiSourceFrameReference() : base() { }
        internal MultiSourceFrameReference(IMultiSourceFrameReference arg) : base(arg) { }
    }

    public class MultiSourceFrameArrivedEventArgs : FrameArrivedEventArgs<IMultiSourceFrameArrivedEventArgs, MultiSourceFrameReference>
    {
        public MultiSourceFrameArrivedEventArgs() : base() { }
        internal MultiSourceFrameArrivedEventArgs(IMultiSourceFrameArrivedEventArgs arg) : base(arg) { }
    }

    public class MultiSourceFrameReader : BaseEvent<IMultiSourceFrameReader, MultiSourceFrameArrivedEventArgs>
    {
        public MultiSourceFrameReader() : base("SubscribeMultiSourceFrameArrived", "UnsubscribeMultiSourceFrameArrived", "GetMultiSourceFrameArrivedEventData") { }
        internal MultiSourceFrameReader(IMultiSourceFrameReader arg) : base(arg, "SubscribeMultiSourceFrameArrived", "UnsubscribeMultiSourceFrameArrived", "GetMultiSourceFrameArrivedEventData") { }
        public FrameSourceTypes FrameSourceTypes
        {
            get { return (FrameSourceTypes)GetMember<DWORD>("FrameSourceTypes"); }
        }
        public bool IsPaused
        {
            get
            {
                try { return origin.get_IsPaused(); }
                catch { }
                return false;
            }
            set
            {
                try { origin.put_IsPaused(value); }
                catch { }
            }
        }
        public KinectSensor KinectSensor
        {
            get { return GetWrappedClass<KinectSensor>("KinectSensor"); }

        }
        public event EventHandler<MultiSourceFrameArrivedEventArgs> FrameArrived
        {
            add { Add_EventHandler(value); }
            remove { Remove_EventHandler(value); }
        }
    }

    public class MultiSourceFrame : BaseInterfaceWrap<IMultiSourceFrame>
    {
        public MultiSourceFrame() : base() { }
        internal MultiSourceFrame(IMultiSourceFrame arg) : base(arg) { }
        public BodyFrameReference BodyFrameReference
        {
            get { return GetWrappedClass<BodyFrameReference>("BodyFrameReference"); }
        }
        public BodyIndexFrameReference BodyIndexFrameReference
        {
            get { return GetWrappedClass<BodyIndexFrameReference>("BodyIndexFrameReference"); }
        }
        public ColorFrameReference ColorFrameReference
        {
            get { return GetWrappedClass<ColorFrameReference>("ColorFrameReference"); }
        }
        public DepthFrameReference DepthFrameReference
        {
            get { return GetWrappedClass<DepthFrameReference>("DepthFrameReference"); }
        }
        public InfraredFrameReference InfraredFrameReference
        {
            get { return GetWrappedClass<InfraredFrameReference>("InfraredFrameReference"); }
        }
        public LongExposureInfraredFrameReference LongExposureInfraredFrameReference
        {
            get { return GetWrappedClass<LongExposureInfraredFrameReference>("LongExposureInfraredFrameReference"); }
        }
    }

    public class ColorFrameReference : FrameReference<IColorFrameReference, ColorFrame>
    {
        public ColorFrameReference() : base() { }
        public ColorFrameReference(IColorFrameReference arg) : base(arg) { }
    }

    public class ColorFrameSource : FrameSourceWithDescription<IColorFrameSource, ColorFrameReader>
    {
        public ColorFrameSource() : base() { }
        public ColorFrameSource(IColorFrameSource arg) : base(arg) { }
        public FrameDescription CreateFrameDescription(ColorImageFormat format)
        {
            try { return new FrameDescription(origin.CreateFrameDescription(format)); }
            catch { }
            return null;
        }
    }

    public class ColorFrameArrivedEventArgs : FrameArrivedEventArgs<IColorFrameArrivedEventArgs, ColorFrameReference>
    {
        public ColorFrameArrivedEventArgs() : base() { }
        public ColorFrameArrivedEventArgs(IColorFrameArrivedEventArgs arg) : base(arg) { }
    }

    public class ColorFrameReader : FrameReaderWithAcquire<IColorFrameReader, ColorFrame, ColorFrameArrivedEventArgs>
    {
        public ColorFrameReader() : base() { }
        internal ColorFrameReader(IColorFrameReader arg) : base(arg) { }
        public ColorFrameSource ColorFrameSource
        {
            get { return GetWrappedClass<ColorFrameSource>("ColorFrameSource"); }
        }
    }

    public class ColorFrame : BaseInterfaceWrap<IColorFrame>
    {
        public ColorFrame() : base() { }
        public ColorFrame(IColorFrame arg) : base(arg) { }
        public ColorCameraSettings ColorCameraSettings
        {
            get { return GetWrappedClass<ColorCameraSettings>("ColorCameraSettings"); }
        }
        public ColorFrameSource ColorFrameSource
        {
            get { return GetWrappedClass<ColorFrameSource>("ColorFrameSource"); }
        }
        public FrameDescription FrameDescription
        {
            get { return GetWrappedClass<FrameDescription>("FrameDescription"); }
        }
        public ColorImageFormat RawColorImageFormat
        {
            get { return GetMember<ColorImageFormat>("RawColorImageFormat"); }
        }
        public TimeSpan RelativeTime
        {
            get { return GetTimeSpan("RelativeTime"); }
        }
        public void CopyConvertedFrameDataToArray(byte[] frameData, ColorImageFormat colorFormat)
        {
			GCHandle gch1 = GCHandle.Alloc (frameData, GCHandleType.Pinned);
            try
            {
                origin.CopyConvertedFrameDataToArray((uint)frameData.Length, gch1.AddrOfPinnedObject(), colorFormat);
            }
            catch { }
            finally
            {
				gch1.Free();
            }
        }
        public void CopyConvertedFrameDataToIntPtr(IntPtr frameData, uint size, ColorImageFormat colorFormat)
        {
            try { origin.CopyConvertedFrameDataToArray(size, frameData, colorFormat); }
            catch { }
        }
        public void CopyRawFrameDataToArray(byte[] frameData)
        {
			GCHandle gch1 = GCHandle.Alloc (frameData, GCHandleType.Pinned);
			try
			{
                origin.CopyRawFrameDataToArray((uint)frameData.Length, gch1.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
				gch1.Free();
            }
        }
        public void CopyRawFrameDataToIntPtr(IntPtr frameData, uint size)
        {
            try { origin.CopyRawFrameDataToArray(size, frameData); }
            catch { }
        }
        public FrameDescription CreateFrameDescription(ColorImageFormat format)
        {
            try { return new FrameDescription(origin.CreateFrameDescription(format)); }
            catch { }
            return null;
        }
        public KinectBuffer LockRawImageBuffer()
        {
            try
            {
                uint size = 0;
                IntPtr ptr = IntPtr.Zero;
                origin.AccessRawUnderlyingBuffer(out size, out ptr);
                return new KinectBuffer(ptr, size);
            }
            catch { }
            return null;
        }
    }

    public class ColorCameraSettings : BaseInterfaceWrap<IColorCameraSettings>
    {
        public ColorCameraSettings() : base() { }
        public ColorCameraSettings(IColorCameraSettings arg) : base(arg) { }
        public TimeSpan ExposureTime
        {
            get { return GetTimeSpan("ExposureTime"); }
        }
        public TimeSpan FrameInterval
        {
            get { return GetTimeSpan("FrameInterval"); }
        }
        public float Gain
        {
            get { return GetMember<float>("Gain"); }
        }
        public float Gamma
        {
            get { return GetMember<float>("Gamma"); }
        }
    }

    public class DepthFrameReference : FrameReference<IDepthFrameReference, DepthFrame>
    {
        public DepthFrameReference() : base() { }
        internal DepthFrameReference(IDepthFrameReference arg) : base(arg) { }
    }

    public class DepthFrameSource : FrameSourceWithDescription<IDepthFrameSource, DepthFrameReader>
    {
        public DepthFrameSource() : base() { }
        internal DepthFrameSource(IDepthFrameSource arg) : base(arg) { }
        public ushort DepthMaxReliableDistance
        {
            get { return GetMember<ushort>("DepthMaxReliableDistance"); }
        }
        public ushort DepthMinReliableDistance
        {
            get { return GetMember<ushort>("DepthMinReliableDistance"); }
        }
    }

    public class DepthFrameArrivedEventArgs : FrameArrivedEventArgs<IDepthFrameArrivedEventArgs, DepthFrameReference>
    {
        public DepthFrameArrivedEventArgs() : base() { }
        internal DepthFrameArrivedEventArgs(IDepthFrameArrivedEventArgs arg) : base(arg) { }
    }

    public class DepthFrameReader : FrameReaderWithAcquire<IDepthFrameReader, DepthFrame, DepthFrameArrivedEventArgs>
    {
        public DepthFrameReader() : base() { }
        internal DepthFrameReader(IDepthFrameReader arg) : base(arg) { }
        public DepthFrameSource DepthFrameSource
        {
            get { return GetWrappedClass<DepthFrameSource>("DepthFrameSource"); }
        }
    }

    public class DepthFrame : BaseInterfaceWrap<IDepthFrame>
    {
        public DepthFrame() : base() { }
        internal DepthFrame(IDepthFrame arg) : base(arg) { }
        public DepthFrameSource DepthFrameSource
        {
            get { return GetWrappedClass<DepthFrameSource>("DepthFrameSource"); }
        }
        public ushort DepthMaxReliableDistance
        {
            get { return GetMember<ushort>("DepthMaxReliableDistance"); }
        }
        public ushort DepthMinReliableDistance
        {
            get { return GetMember<ushort>("DepthMinReliableDistance"); }
        }
        public FrameDescription FrameDescription
        {
            get { return GetWrappedClass<FrameDescription>("FrameDescription"); }
        }
        public TimeSpan RelativeTime
        {
            get { return GetTimeSpan("RelativeTime"); }
        }
        public void CopyFrameDataToArray(ushort[] frameData)
        {
			GCHandle gch1 = GCHandle.Alloc (frameData, GCHandleType.Pinned);
            try
            {
				origin.CopyFrameDataToArray((uint)frameData.Length, gch1.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
				gch1.Free();
            }
        }
        public void CopyFrameDataToIntPtr(IntPtr frameData, uint size)
        {
            try { origin.CopyFrameDataToArray(size / sizeof(ushort), frameData); }
            catch { }
        }
        public KinectBuffer LockImageBuffer()
        {
            try
            {
                uint size = 0;
                IntPtr ptr = IntPtr.Zero;
                origin.AccessUnderlyingBuffer(out size, out ptr);
                return new KinectBuffer(ptr, size * sizeof(ushort));
            }
            catch { }
            return null;
        }
    }

    public class BodyFrameReference : FrameReference<IBodyFrameReference, BodyFrame>
    {
        public BodyFrameReference() : base() { }
        internal BodyFrameReference(IBodyFrameReference arg) : base(arg) { }
    }

    public class BodyFrameSource : FrameSource<IBodyFrameSource, BodyFrameReader>
    {
        public BodyFrameSource() : base() { }
        internal BodyFrameSource(IBodyFrameSource arg) : base(arg) { }
        public int BodyCount
        {
            get { return GetMember<int>("BodyCount"); }
        }
        public void OverrideHandTracking(ulong trackingId)
        {
            try { origin.OverrideHandTracking(trackingId); }
            catch { }
        }
        public void OverrideAndReplaceHandTracking(ulong oldTrackingId, ulong newTrackingId)
        {
            try { origin.OverrideAndReplaceHandTracking(oldTrackingId, newTrackingId); }
            catch { }
        }
    }

    public class BodyFrameArrivedEventArgs : FrameArrivedEventArgs<IBodyFrameArrivedEventArgs, BodyFrameReference>
    {
        public BodyFrameArrivedEventArgs() : base() { }
        internal BodyFrameArrivedEventArgs(IBodyFrameArrivedEventArgs arg) : base(arg) { }
    }

    public class BodyFrameReader : FrameReaderWithAcquire<IBodyFrameReader, BodyFrame, BodyFrameArrivedEventArgs>
    {
        public BodyFrameReader() : base() { }
        internal BodyFrameReader(IBodyFrameReader arg) : base(arg) { }
        public BodyFrameSource BodyFrameSource
        {
            get { return GetWrappedClass<BodyFrameSource>("BodyFrameSource"); }
        }
    }

    public class BodyFrame : BaseInterfaceWrap<IBodyFrame>
    {
        public BodyFrame() : base() { }
        internal BodyFrame(IBodyFrame arg) : base(arg) { }
        public int BodyCount
        {
            get { return Kinect.BODY_COUNT; }
        }
        public BodyFrameSource BodyFrameSource
        {
            get { return GetWrappedClass<BodyFrameSource>("BodyFrameSource"); }
        }
        public Vector4 FloorClipPlane
        {
            get { return GetMember<Vector4>("FloorClipPlane"); }
        }
        public TimeSpan RelativeTime
        {
            get { return GetTimeSpan("RelativeTime"); }
        }
        public void GetAndRefreshBodyData(IList<Body> bodies)
        {
            try
            {
                IntPtr[] ptrs = new IntPtr[BodyCount];
                origin.GetAndRefreshBodyData((uint)ptrs.Length, ptrs);
                for (int i = 0; i < ptrs.Length && i < bodies.Count; i++)
                {
                    if (ptrs[i] == IntPtr.Zero)
                        bodies[i] = null;
                    else
                        bodies[i] = new Body(Marshal.GetObjectForIUnknown(ptrs[i]) as IBody);
                }
            }
            catch
            {
                for (int i = 0; i < bodies.Count; i++)
                    bodies[i] = null;
            }
        }
    }

    public class Body : BaseInterfaceWrap<IBody>
    {
        public Body() : base() { }
        internal Body(IBody arg) : base(arg) { }

        public FrameEdges ClippedEdges
        {
            get { return (FrameEdges)GetMember<DWORD>("ClippedEdges"); }
        }
        public DetectionResult Engaged
        {
            get { return GetMember<DetectionResult>("Engaged"); }
        }
        public ulong TrackingId
        {
            get { return GetMember<ulong>("TrackingId"); }
        }
        public TrackingConfidence HandLeftConfidence
        {
            get { return GetMember<TrackingConfidence>("HandLeftConfidence"); }
        }
        public TrackingConfidence HandRightConfidence
        {
            get { return GetMember<TrackingConfidence>("HandRightConfidence"); }
        }
        public HandState HandLeftState
        {
            get { return GetMember<HandState>("HandLeftState"); }
        }
        public HandState HandRightState
        {
            get { return GetMember<HandState>("HandRightState"); }
        }
        public bool IsRestricted
        {
            get { return GetMember<bool>("IsRestricted"); }
        }
        public bool IsTracked
        {
            get { return GetMember<bool>("IsTracked"); }
        }
        public static int JointCount
        {
            get { return (int)JointType.Count; }
        }
        public PointF Lean
        {
            get { return GetMember<PointF>("Lean"); }
        }
        public TrackingState LeanTrackingState
        {
            get { return GetMember<TrackingState>("LeanTrackingState"); }
        }
        public IDictionary<Activity, DetectionResult> Activities
        {
            get
            {
                try
                {
                    Dictionary<Activity, DetectionResult> dict = new Dictionary<Activity, DetectionResult>((int)Activity.Count);
                    DetectionResult[] detectionResults = new DetectionResult[(int)Activity.Count];
                    for (int i = 0; i < detectionResults.Length; i++)
                        dict.Add((Activity)i, DetectionResult.Unknown);
                    origin.GetActivityDetectionResults((uint)detectionResults.Length, detectionResults);
                    for (int i = 0; i < detectionResults.Length; i++)
                        dict[(Activity)i] = detectionResults[i];
                    return dict;
                }
                catch { }
                return null;
            }
        }
        public IDictionary<Appearance, DetectionResult> Appearance
        {
            get
            {
                try
                {
                    Dictionary<Appearance, DetectionResult> dict = new Dictionary<Appearance, DetectionResult>((int)Kinect2.Appearance.Count);
                    DetectionResult[] detectionResults = new DetectionResult[(int)Kinect2.Appearance.Count];
                    for (int i = 0; i < detectionResults.Length; i++)
                        dict.Add((Appearance)i, DetectionResult.Unknown);
                    origin.GetAppearanceDetectionResults((uint)detectionResults.Length, detectionResults);
                    for (int i = 0; i < detectionResults.Length; i++)
                        dict[(Appearance)i] = detectionResults[i];
                    return dict;
                }
                catch { }
                return null;
            }
        }
        public IDictionary<Expression, DetectionResult> Expressions
        {
            get
            {
                try
                {
                    Dictionary<Expression, DetectionResult> dict = new Dictionary<Expression, DetectionResult>((int)Expression.Count);
                    DetectionResult[] detectionResults = new DetectionResult[(int)Expression.Count];
                    for (int i = 0; i < detectionResults.Length; i++)
                        dict.Add((Expression)i, DetectionResult.Unknown);
                    origin.GetExpressionDetectionResults((uint)detectionResults.Length, detectionResults);
                    for (int i = 0; i < detectionResults.Length; i++)
                        dict[(Expression)i] = detectionResults[i];
                    return dict;
                }
                catch { }
                return null;
            }
        }
        public IDictionary<JointType, Joint> Joints
        {
            get
            {
                try
                {
                    Dictionary<JointType, Joint> dict = new Dictionary<JointType, Joint>((int)JointType.Count);
                    Joint[] joints = new Joint[(int)JointType.Count];
                    for (int i = 0; i < joints.Length; i++)
                        dict.Add((JointType)i, joints[i]);
                    origin.GetJoints((uint)joints.Length, joints);
                    for (int i = 0; i < joints.Length; i++)
                        dict[(JointType)i] = joints[i];
                    return dict;
                }
                catch { }
                return null;
            }
        }
        public IDictionary<JointType, JointOrientation> JointOrientations
        {
            get
            {
                try
                {
                    Dictionary<JointType, JointOrientation> dict = new Dictionary<JointType, JointOrientation>((int)JointType.Count);
                    JointOrientation[] JointOrientations = new JointOrientation[(int)JointType.Count];
                    for (int i = 0; i < JointOrientations.Length; i++)
                        dict.Add((JointType)i, JointOrientations[i]);
                    origin.GetJointOrientations((uint)JointOrientations.Length, JointOrientations);
                    for (int i = 0; i < JointOrientations.Length; i++)
                        dict[(JointType)i] = JointOrientations[i];
                    return dict;
                }
                catch { }
                return null;
            }
        }
    }

    public class BodyIndexFrameReference : FrameReference<IBodyIndexFrameReference, BodyIndexFrame>
    {
        public BodyIndexFrameReference() : base() { }
        internal BodyIndexFrameReference(IBodyIndexFrameReference arg) : base(arg) { }
    }

    public class BodyIndexFrameSource : FrameSourceWithDescription<IBodyIndexFrameSource, BodyIndexFrameReader>
    {
        public BodyIndexFrameSource() : base() { }
        internal BodyIndexFrameSource(IBodyIndexFrameSource arg) : base(arg) { }
    }

    public class BodyIndexFrameArrivedEventArgs : FrameArrivedEventArgs<IBodyIndexFrameArrivedEventArgs, BodyIndexFrameReference>
    {
        public BodyIndexFrameArrivedEventArgs() : base() { }
        internal BodyIndexFrameArrivedEventArgs(IBodyIndexFrameArrivedEventArgs arg) : base(arg) { }
    }

    public class BodyIndexFrameReader : FrameReaderWithAcquire<IBodyIndexFrameReader, BodyIndexFrame, BodyFrameArrivedEventArgs>
    {
        public BodyIndexFrameReader() : base() { }
        internal BodyIndexFrameReader(IBodyIndexFrameReader arg) : base(arg) { }
        public BodyIndexFrameSource BodyIndexFrameSource
        {
            get { return GetWrappedClass<BodyIndexFrameSource>("BodyIndexFrameSource"); }
        }
    }

    public class BodyIndexFrame : BaseInterfaceWrap<IBodyIndexFrame>
    {
        public BodyIndexFrame() : base() { }
        internal BodyIndexFrame(IBodyIndexFrame arg) : base(arg) { }
        public BodyIndexFrameSource BodyIndexFrameSource
        {
            get { return GetWrappedClass<BodyIndexFrameSource>("BodyIndexFrameSource"); }
        }
        public FrameDescription FrameDescription
        {
            get { return GetWrappedClass<FrameDescription>("FrameDescription"); }
        }
        public TimeSpan RelativeTime
        {
            get { return GetTimeSpan("RelativeTime"); }
        }
        public void CopyFrameDataToArray(byte[] frameData)
        {
			GCHandle gch1 = GCHandle.Alloc (frameData, GCHandleType.Pinned);
            try
            {
                origin.CopyFrameDataToArray((uint)frameData.Length, gch1.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
				gch1.Free();
            }
        }
        public void CopyFrameDataToIntPtr(IntPtr frameData, uint size)
        {
            try { origin.CopyFrameDataToArray(size, frameData); }
            catch { }
        }
        public KinectBuffer LockImageBuffer()
        {
            try
            {
                uint size = 0;
                IntPtr ptr = IntPtr.Zero;
                origin.AccessUnderlyingBuffer(out size, out ptr);
                return new KinectBuffer(ptr, size);
            }
            catch { }
            return null;
        }
    }

    public class InfraredFrameReference : FrameReference<IInfraredFrameReference, InfraredFrame>
    {
        public InfraredFrameReference() : base() { }
        internal InfraredFrameReference(IInfraredFrameReference arg) : base(arg) { }
    }

    public class InfraredFrameSource : FrameSourceWithDescription<IInfraredFrameSource, InfraredFrameReader>
    {
        public InfraredFrameSource() : base() { }
        internal InfraredFrameSource(IInfraredFrameSource arg) : base(arg) { }
    }

    public class InfraredFrameArrivedEventArgs : FrameArrivedEventArgs<IInfraredFrameArrivedEventArgs, InfraredFrameReference>
    {
        public InfraredFrameArrivedEventArgs() : base() { }
        internal InfraredFrameArrivedEventArgs(IInfraredFrameArrivedEventArgs arg) : base(arg) { }
    }

    public class InfraredFrameReader : FrameReaderWithAcquire<IInfraredFrameReader, InfraredFrame, InfraredFrameArrivedEventArgs>
    {
        public InfraredFrameReader() : base() { }
        internal InfraredFrameReader(IInfraredFrameReader arg) : base(arg) { }
        public InfraredFrameSource InfraredFrameSource
        {
            get { return GetWrappedClass<InfraredFrameSource>("InfraredFrameSource"); }
        }
    }

    public class InfraredFrame : BaseInterfaceWrap<IInfraredFrame>
    {
        public InfraredFrame() : base() { }
        internal InfraredFrame(IInfraredFrame arg) : base(arg) { }
        public InfraredFrameSource InfraredFrameSource
        {
            get { return GetWrappedClass<InfraredFrameSource>("InfraredFrameSource"); }
        }
        public FrameDescription FrameDescription
        {
            get { return GetWrappedClass<FrameDescription>("FrameDescription"); }
        }
        public TimeSpan RelativeTime
        {
            get { return GetTimeSpan("RelativeTime"); }
        }
        public void CopyFrameDataToArray(ushort[] frameData)
        {
			GCHandle gch1 = GCHandle.Alloc (frameData, GCHandleType.Pinned);
            try
            {
                origin.CopyFrameDataToArray((uint)frameData.Length, gch1.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
            }
        }
        public void CopyFrameDataToIntPtr(IntPtr frameData, uint size)
        {
            try { origin.CopyFrameDataToArray(size / sizeof(ushort), frameData); }
            catch { }
        }
        public KinectBuffer LockImageBuffer()
        {
            try
            {
                uint size = 0;
                IntPtr ptr = IntPtr.Zero;
                origin.AccessUnderlyingBuffer(out size, out ptr);
                return new KinectBuffer(ptr, size * sizeof(ushort));
            }
            catch { }
            return null;
        }
    }

    public class LongExposureInfraredFrameReference : FrameReference<ILongExposureInfraredFrameReference, LongExposureInfraredFrame>
    {
        public LongExposureInfraredFrameReference() : base() { }
        internal LongExposureInfraredFrameReference(ILongExposureInfraredFrameReference arg) : base(arg) { }
    }

    public class LongExposureInfraredFrameSource : FrameSourceWithDescription<ILongExposureInfraredFrameSource, LongExposureInfraredFrameReader>
    {
        public LongExposureInfraredFrameSource() : base() { }
        internal LongExposureInfraredFrameSource(ILongExposureInfraredFrameSource arg) : base(arg) { }
    }

    public class LongExposureInfraredFrameArrivedEventArgs : FrameArrivedEventArgs<ILongExposureInfraredFrameArrivedEventArgs, LongExposureInfraredFrameReference>
    {
        public LongExposureInfraredFrameArrivedEventArgs() : base() { }
        internal LongExposureInfraredFrameArrivedEventArgs(ILongExposureInfraredFrameArrivedEventArgs arg) : base(arg) { }
    }

    public class LongExposureInfraredFrameReader : FrameReaderWithAcquire<ILongExposureInfraredFrameReader, LongExposureInfraredFrame, LongExposureInfraredFrameArrivedEventArgs>
    {
        public LongExposureInfraredFrameReader() : base() { }
        internal LongExposureInfraredFrameReader(ILongExposureInfraredFrameReader arg) : base(arg) { }
        public LongExposureInfraredFrameSource LongExposureInfraredFrameSource
        {
            get { return GetWrappedClass<LongExposureInfraredFrameSource>("LongExposureInfraredFrameSource"); }
        }
    }

    public class LongExposureInfraredFrame : BaseInterfaceWrap<ILongExposureInfraredFrame>
    {
        public LongExposureInfraredFrame() : base() { }
        internal LongExposureInfraredFrame(ILongExposureInfraredFrame arg) : base(arg) { }
        public LongExposureInfraredFrameSource LongExposureInfraredFrameSource
        {
            get { return GetWrappedClass<LongExposureInfraredFrameSource>("LongExposureInfraredFrameSource"); }
        }
        public FrameDescription FrameDescription
        {
            get { return GetWrappedClass<FrameDescription>("FrameDescription"); }
        }
        public TimeSpan RelativeTime
        {
            get { return GetTimeSpan("RelativeTime"); }
        }
        public void CopyFrameDataToArray(ushort[] frameData)
        {
			GCHandle gch1 = GCHandle.Alloc (frameData, GCHandleType.Pinned);
            try
            {
				origin.CopyFrameDataToArray((uint)frameData.Length, gch1.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
				gch1.Free();
            }
        }
        public void CopyFrameDataToIntPtr(IntPtr frameData, uint size)
        {
            try { origin.CopyFrameDataToArray(size / sizeof(ushort), frameData); }
            catch { }
        }
        public KinectBuffer LockImageBuffer()
        {
            try
            {
                uint size = 0;
                IntPtr ptr = IntPtr.Zero;
                origin.AccessUnderlyingBuffer(out size, out ptr);
                return new KinectBuffer(ptr, size * sizeof(ushort));
            }
            catch { }
            return null;
        }
    }

    public class CoordinateMapper : BaseInterfaceWrap<ICoordinateMapper>
    {
        public CoordinateMapper() : base() { }
        public CoordinateMapper(ICoordinateMapper arg) : base(arg) { }
        public CameraIntrinsics GetDepthCameraIntrinsics()
        {
            try { return origin.GetDepthCameraIntrinsics(); }
            catch { }
            return new CameraIntrinsics();
        }
        public PointF[] GetDepthFrameToCameraSpaceTable()
        {
            try
            {
                UInt32 tableEntryCount = 0;
                return origin.GetDepthFrameToCameraSpaceTable(out tableEntryCount);
            }
            catch { }
            return null;
        }
        public void MapCameraPointsToColorSpace(CameraSpacePoint[] cameraPoints, ColorSpacePoint[] colorPoints)
        {
            GCHandle gch1 = GCHandle.Alloc(cameraPoints, GCHandleType.Pinned);
			GCHandle gch2 = GCHandle.Alloc(colorPoints, GCHandleType.Pinned);
			try
            {
                origin.MapCameraPointsToColorSpace((uint)cameraPoints.Length,
                    gch1.AddrOfPinnedObject(),
                    (uint)colorPoints.Length,
					gch2.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
                gch2.Free();
            }
        }
        public void MapCameraPointsToColorSpaceUsingIntPtr(IntPtr cameraPoints, uint cameraPointsSize, IntPtr colorPoints, uint colorPointsSize)
        {
            try
            {
                origin.MapCameraPointsToColorSpace(cameraPointsSize / (uint)Marshal.SizeOf(typeof(CameraSpacePoint)),
                    cameraPoints,
                    colorPointsSize / (uint)Marshal.SizeOf(typeof(ColorSpacePoint)),
                    colorPoints);
            }
            catch { }
        }
        public void MapCameraPointsToDepthSpace(CameraSpacePoint[] cameraPoints, DepthSpacePoint[] depthPoints)
        {
			GCHandle gch1 = GCHandle.Alloc(cameraPoints, GCHandleType.Pinned);
			GCHandle gch2 = GCHandle.Alloc(depthPoints, GCHandleType.Pinned);
            try
            {
                origin.MapCameraPointsToDepthSpace((uint)cameraPoints.Length,
                    gch1.AddrOfPinnedObject(),
                    (uint)depthPoints.Length,
                    gch2.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
                gch2.Free();
            }
        }
        public void MapCameraPointsToDepthSpaceUsingIntPtr(IntPtr cameraPoints, uint cameraPointsSize, IntPtr depthPoints, uint depthPointsSize)
        {
            try
            {
                origin.MapCameraPointsToDepthSpace(cameraPointsSize / (uint)Marshal.SizeOf(typeof(CameraSpacePoint)),
                    cameraPoints,
                    depthPointsSize / (uint)Marshal.SizeOf(typeof(DepthSpacePoint)),
                    depthPoints);
            }
            catch { }
        }
        public ColorSpacePoint MapCameraPointToColorSpace(CameraSpacePoint cameraPoint)
        {
            try { return origin.MapCameraPointToColorSpace(cameraPoint); }
            catch { }
            return new ColorSpacePoint();
        }
        public DepthSpacePoint MapCameraPointToDepthSpace(CameraSpacePoint cameraPoint)
        {
            try { return origin.MapCameraPointToDepthSpace(cameraPoint); }
            catch { }
            return new DepthSpacePoint();
        }
        public void MapColorFrameToCameraSpace(ushort[] depthFrameData, CameraSpacePoint[] cameraSpacePoints)
        {
			GCHandle gch1 = GCHandle.Alloc(depthFrameData, GCHandleType.Pinned);
			GCHandle gch2 = GCHandle.Alloc(cameraSpacePoints, GCHandleType.Pinned);
            try
            {
                origin.MapColorFrameToCameraSpace((uint)depthFrameData.Length,
                    gch1.AddrOfPinnedObject(),
                    (uint)cameraSpacePoints.Length,
                    gch2.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
                gch2.Free();
            }
        }
        public void MapColorFrameToCameraSpaceUsingIntPtr(IntPtr depthFrameData, uint depthFrameSize, CameraSpacePoint[] cameraSpacePoints)
        {
			GCHandle gch1 = GCHandle.Alloc(cameraSpacePoints, GCHandleType.Pinned);
			try
            {
                origin.MapColorFrameToCameraSpace(depthFrameSize / sizeof(ushort),
                    depthFrameData,
                    (uint)cameraSpacePoints.Length,
                    gch1.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
            }
        }
        public void MapColorFrameToCameraSpaceUsingIntPtr(IntPtr depthFrameData, uint depthFrameSize, IntPtr cameraSpacePoints, uint cameraSpacePointsSize)
        {
            try
            {
                origin.MapColorFrameToCameraSpace(depthFrameSize / sizeof(ushort),
                    depthFrameData,
                    cameraSpacePointsSize / (uint)Marshal.SizeOf(typeof(CameraSpacePoint)),
                    cameraSpacePoints);
            }
            catch { }
        }
        public void MapColorFrameToDepthSpace(ushort[] depthFrameData, DepthSpacePoint[] depthSpacePoints)
        {
			GCHandle gch1 = GCHandle.Alloc(depthFrameData, GCHandleType.Pinned);
			GCHandle gch2 = GCHandle.Alloc(depthSpacePoints, GCHandleType.Pinned);
            try
            {
                origin.MapColorFrameToDepthSpace((uint)depthFrameData.Length,
                    gch1.AddrOfPinnedObject(),
                    (uint)depthSpacePoints.Length,
                    gch2.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
                gch2.Free();
            }
        }
        public void MapColorFrameToDepthSpaceUsingIntPtr(IntPtr depthFrameData, uint depthFrameSize, DepthSpacePoint[] depthSpacePoints)
        {
			GCHandle gch1 = GCHandle.Alloc(depthSpacePoints, GCHandleType.Pinned);
            try
            {

                origin.MapColorFrameToDepthSpace(depthFrameSize / sizeof(ushort),
                    depthFrameData,
                    (uint)depthSpacePoints.Length,
                    gch1.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
            }
        }
        public void MapColorFrameToDepthSpaceUsingIntPtr(IntPtr depthFrameData, uint depthFrameSize, IntPtr depthSpacePoints, uint depthSpacePointsSize)
        {
            try
            {
                origin.MapColorFrameToDepthSpace(depthFrameSize / sizeof(ushort),
                    depthFrameData,
                    depthSpacePointsSize / (uint)Marshal.SizeOf(typeof(DepthSpacePoint)),
                    depthSpacePoints);
            }
            catch { }
        }
        public void MapDepthFrameToCameraSpace(ushort[] depthFrameData, CameraSpacePoint[] cameraSpacePoints)
        {
			GCHandle gch1 = GCHandle.Alloc(depthFrameData, GCHandleType.Pinned);
			GCHandle gch2 = GCHandle.Alloc(cameraSpacePoints, GCHandleType.Pinned);
            try
            {
                origin.MapDepthFrameToCameraSpace((uint)depthFrameData.Length,
                    gch1.AddrOfPinnedObject(),
                    (uint)cameraSpacePoints.Length,
                    gch2.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
                gch2.Free();
            }
        }
        public void MapDepthFrameToCameraSpaceUsingIntPtr(IntPtr depthFrameData, uint depthFrameSize, CameraSpacePoint[] cameraSpacePoints)
        {
			GCHandle gch1 = GCHandle.Alloc(cameraSpacePoints, GCHandleType.Pinned);
			try
            {
                origin.MapDepthFrameToCameraSpace(depthFrameSize / sizeof(ushort),
                    depthFrameData,
                    (uint)cameraSpacePoints.Length,
                    gch1.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
            }
        }
        public void MapDepthFrameToCameraSpaceUsingIntPtr(IntPtr depthFrameData, uint depthFrameSize, IntPtr cameraSpacePoints, uint cameraSpacePointsSize)
        {
            try
            {
                origin.MapDepthFrameToCameraSpace(depthFrameSize / sizeof(ushort),
                    depthFrameData,
                    cameraSpacePointsSize / (uint)Marshal.SizeOf(typeof(CameraSpacePoint)), cameraSpacePoints);
            }
            catch { }
        }
        public void MapDepthFrameToColorSpace(ushort[] depthFrameData, ColorSpacePoint[] colorSpacePoints)
        {
			GCHandle gch1 = GCHandle.Alloc(depthFrameData, GCHandleType.Pinned);
			GCHandle gch2 = GCHandle.Alloc(colorSpacePoints, GCHandleType.Pinned);
            try
            {
                origin.MapDepthFrameToColorSpace((uint)depthFrameData.Length,
                    gch1.AddrOfPinnedObject(),
                    (uint)colorSpacePoints.Length,
                    gch2.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
                gch2.Free();
            }
        }
        public void MapDepthFrameToColorSpaceUsingIntPtr(IntPtr depthFrameData, uint depthFrameSize, ColorSpacePoint[] colorSpacePoints)
        {
			GCHandle gch1 = GCHandle.Alloc(colorSpacePoints, GCHandleType.Pinned);
			try
            {
                origin.MapDepthFrameToColorSpace(depthFrameSize / sizeof(ushort),
                    depthFrameData,
                    (uint)colorSpacePoints.Length,
                    gch1.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
            }
        }
        public void MapDepthFrameToColorSpaceUsingIntPtr(IntPtr depthFrameData, uint depthFrameSize, IntPtr colorSpacePoints, uint colorSpacePointsSize)
        {
            try
            {
                uint depthFrameDataCount = depthFrameSize / sizeof(ushort);
                uint colorSpacePointsCount = colorSpacePointsSize / (uint)Marshal.SizeOf(typeof(ColorSpacePoint));
                origin.MapDepthFrameToColorSpace(depthFrameDataCount, depthFrameData, colorSpacePointsCount, colorSpacePoints);
            }
            catch { }
        }
        public void MapDepthPointsToCameraSpace(DepthSpacePoint[] depthPoints, ushort[] depths, CameraSpacePoint[] cameraPoints)
        {
			GCHandle gch1 = GCHandle.Alloc(depthPoints, GCHandleType.Pinned);
			GCHandle gch2 = GCHandle.Alloc(depths, GCHandleType.Pinned);
			GCHandle gch3 = GCHandle.Alloc(cameraPoints, GCHandleType.Pinned);
			try
            {
                origin.MapDepthPointsToCameraSpace(
                    (uint)depthPoints.Length,
                    gch1.AddrOfPinnedObject(),
                    (uint)depths.Length,
                    gch2.AddrOfPinnedObject(),
                    (uint)cameraPoints.Length,
                    gch3.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
                gch2.Free();
                gch3.Free();

            }
        }
        public void MapDepthPointsToCameraSpaceUsingPtr(IntPtr depthPoints, uint depthPointsSize, IntPtr depths, uint depthsSize, IntPtr cameraPoints, uint cameraPointsSize)
        {
            try
            {
                origin.MapDepthPointsToCameraSpace(depthPointsSize / (uint)Marshal.SizeOf(typeof(DepthSpacePoint)),
                    depthPoints,
                    depthsSize / sizeof(ushort),
                    depths,
                    cameraPointsSize / (uint)Marshal.SizeOf(typeof(CameraSpacePoint)),
                    cameraPoints);
            }
            catch { }
        }
        public void MapDepthPointsToColorSpace(DepthSpacePoint[] depthPoints, ushort[] depths, ColorSpacePoint[] colorPoints)
        {
			GCHandle gch1 = GCHandle.Alloc(depthPoints, GCHandleType.Pinned);
			GCHandle gch2 = GCHandle.Alloc(depths, GCHandleType.Pinned);
			GCHandle gch3 = GCHandle.Alloc(colorPoints, GCHandleType.Pinned);
			try
            {
                origin.MapDepthPointsToColorSpace((uint)depthPoints.Length,
                    gch1.AddrOfPinnedObject(),
                    (uint)depths.Length,
                    gch2.AddrOfPinnedObject(),
                    (uint)colorPoints.Length,
                   	gch3.AddrOfPinnedObject());
            }
            catch { }
            finally
            {
                gch1.Free();
                gch2.Free();
                gch3.Free();
            }
        }
        public void MapDepthPointsToColorSpaceUsingPtr(IntPtr depthPoints, uint depthPointsSize, IntPtr depths, uint depthsSize, IntPtr colorPoints, uint colorPointsSize)
        {
            try
            {
                origin.MapDepthPointsToColorSpace(depthPointsSize / (uint)Marshal.SizeOf(typeof(DepthSpacePoint)),
                    depthPoints,
                    depthsSize / sizeof(ushort),
                    depths,
                    colorPointsSize / (uint)Marshal.SizeOf(typeof(ColorSpacePoint)),
                    colorPoints);
            }
            catch { }
        }
        public CameraSpacePoint MapDepthPointToCameraSpace(DepthSpacePoint depthPoint, ushort depth)
        {
            try { return origin.MapDepthPointToCameraSpace(depthPoint, depth); }
            catch { }
            return new CameraSpacePoint();
        }
        public ColorSpacePoint MapDepthPointToColorSpace(DepthSpacePoint depthPoint, ushort depth)
        {
            try { return origin.MapDepthPointToColorSpace(depthPoint, depth); }
            catch { }
            return new ColorSpacePoint();
        }
    }
	
	public class AudioSource : FrameSource<IAudioSource, AudioBeamFrameReader>
    {
        public AudioSource() : base() { }
        internal AudioSource(IAudioSource arg) : base(arg) { }
        public IList<AudioBeam> AudioBeams
        {
            get
            {
                try
                {
                    IAudioBeamList audioBeamList = origin.get_AudioBeams();
                    uint count = audioBeamList.get_BeamCount();
                    List<AudioBeam> list = new List<AudioBeam>((int)count);
                    for (uint i = 0; i < count; i++)
                    {
                        IAudioBeam audioBeam;
                        audioBeamList.OpenAudioBeam(i, out audioBeam);
                        list.Add(new AudioBeam(audioBeam));
                    }
                    Marshal.ReleaseComObject(audioBeamList);
                    return list;
                }
                catch { }
                return null;
            }
        }
        public KinectAudioCalibrationState AudioCalibrationState
        {
            get { return GetMember<KinectAudioCalibrationState>("AudioCalibrationState"); }
        }
        public uint MaxSubFrameCount
        {
            get { return GetMember<uint>("MaxSubFrameCount"); }
        }
        public TimeSpan SubFrameDuration
        {
            get { return GetTimeSpan("SubFrameDuration"); }
        }
        public uint SubFrameLengthInBytes
        {
            get { return GetMember<uint>("SubFrameLengthInBytes"); }
        }
    }

    public class AudioBeamFrameReference : BaseInterfaceWrap<IAudioBeamFrameReference>
    {
        public AudioBeamFrameReference() : base() { }
        internal AudioBeamFrameReference(IAudioBeamFrameReference arg) : base(arg) { }
        public TimeSpan RelativeTime
        {
            get { return GetTimeSpan("RelativeTime"); }
        }
        AudioBeamFrameList AcquireBeamFrames()
        {
            try { return new AudioBeamFrameList(origin.AcquireBeamFrames()); }
            catch { }
            return null;
        }
    }

    public class AudioBeamFrameArrivedEventArgs : FrameArrivedEventArgs<IAudioBeamFrameArrivedEventArgs, AudioBeamFrameReference>
    {
        public AudioBeamFrameArrivedEventArgs() : base() { }
        internal AudioBeamFrameArrivedEventArgs(IAudioBeamFrameArrivedEventArgs arg) : base(arg) { }
    }

    public class AudioBeamFrameReader : FrameReader<IAudioBeamFrameReader, AudioBeamFrameArrivedEventArgs>
    {
        public AudioBeamFrameReader() : base() { }
        internal AudioBeamFrameReader(IAudioBeamFrameReader arg) : base(arg) { }

        public AudioSource AudioSource
        {
            get { return GetWrappedClass<AudioSource>("AudioSource"); }
        }
        public AudioBeamFrameList AcquireLatestFrame()
        {
            try { return new AudioBeamFrameList(origin.AcquireLatestBeamFrames()); }
            catch { }
            return null;
        }
    }

	public class AudioBeamFrameList : BaseInterfaceWrap<IAudioBeamFrameList>, IEnumerable<AudioBeamFrame>
	{
        public AudioBeamFrameList() : base() { }
        internal AudioBeamFrameList(IAudioBeamFrameList arg) : base(arg) { }
        public int Count
        {
            get { return (int)GetMember<uint>("BeamCount"); }
        }
        public AudioBeamFrame this[int index]
        {
            get
            {
                try
                {
                    IAudioBeamFrame audioBeamFrame = null;
                    origin.OpenAudioBeamFrame((uint)index, out audioBeamFrame);
                    return new AudioBeamFrame(audioBeamFrame);
                }
                catch { }
                return null;
            }
        }
		class AudioBeamFrame_Enumerator : IEnumerator<AudioBeamFrame>
		{
			int index = 0;
			AudioBeamFrameList list;
			public AudioBeamFrame_Enumerator(AudioBeamFrameList list) 
			{
				this.list = list;
			}
			public AudioBeamFrame Current 
			{
				get { return list [index]; }
			}
			object IEnumerator.Current 
			{
				get { return this.Current; }
			}
			bool IEnumerator.MoveNext ()
			{
				if (index < list.Count) 
				{
					index += 1;
					return true;
				}
				return false;
			}
			void IEnumerator.Reset ()
			{
				index = 0;
			}
			public void Dispose()
			{
			}
		}
		IEnumerator IEnumerable.GetEnumerator()
		{
			return this.GetEnumerator();
		}
		public IEnumerator<AudioBeamFrame> GetEnumerator()
		{
			return new AudioBeamFrame_Enumerator (this);
		}
    }

    public class AudioBeamFrame : BaseInterfaceWrap<IAudioBeamFrame>
    {
        public AudioBeamFrame() : base() { }
        internal AudioBeamFrame(IAudioBeamFrame arg) : base(arg) { }
        public AudioBeam AudioBeam
        {
            get { return GetWrappedClass<AudioBeam>("AudioBeam"); }
        }
        public AudioSource AudioSource
        {
            get { return GetWrappedClass<AudioSource>("AudioSource"); }
        }
        public TimeSpan Duration
        {
            get { return GetTimeSpan("Duration"); }
        }
        public TimeSpan RelativeTimeStart
        {
            get { return GetTimeSpan("RelativeTimeStart"); }
        }
        public IList<AudioBeamSubFrame> SubFrames
        {
            get
            {
                try
                {
                    uint count = origin.get_SubFrameCount();
                    List<AudioBeamSubFrame> list = new List<AudioBeamSubFrame>((int)count);
                    for (uint i = 0; i < count; i++)
                    {
                        IAudioBeamSubFrame audioBeamSubFrame = null;
                        origin.GetSubFrame(i, out audioBeamSubFrame);
                        list.Add(new AudioBeamSubFrame(audioBeamSubFrame));
                    }
                    return list;
                }
                catch { }
                return null;
            }
        }
    }

    public class AudioBeamSubFrame : BaseInterfaceWrap<IAudioBeamSubFrame>
    {
        public AudioBeamSubFrame() : base() { }
        internal AudioBeamSubFrame(IAudioBeamSubFrame arg) : base(arg) { }
        public AudioBeamMode AudioBeamMode
        {
            get { return GetMember<AudioBeamMode>("AudioBeamMode"); }
        }
        public IList<AudioBodyCorrelation> AudioBodyCorrelations
        {
            get
            {
                try
                {
                    uint count = origin.get_AudioBodyCorrelationCount();
                    List<AudioBodyCorrelation> list = new List<AudioBodyCorrelation>((int)count);
                    for (uint i = 0; i < count; i++)
                    {
                        IAudioBodyCorrelation audioBodyCorrelation = null;
                        origin.GetAudioBodyCorrelation(i, out audioBodyCorrelation);
                        list.Add(new AudioBodyCorrelation(audioBodyCorrelation));
                    }
                    return list;
                }
                catch { }
                return null;
            }
        }
        public float BeamAngle
        {
            get { return GetMember<float>("BeamAngle"); }
        }
        public float BeamAngleConfidence
        {
            get { return GetMember<float>("BeamAngleConfidence"); }
        }
        public uint FrameLengthInBytes
        {
            get { return GetMember<uint>("FrameLengthInBytes"); }
        }
        public TimeSpan Duration
        {
            get { return GetTimeSpan("Duration"); }
        }
        public TimeSpan RelativeTime
        {
            get { return GetTimeSpan("RelativeTime"); }
        }
        public void CopyFrameDataToArray(byte[] frameData)
        {
            IntPtr frameDataPtr = IntPtr.Zero;
            try
            {
                frameDataPtr = Marshal.AllocCoTaskMem(frameData.Length);
                origin.CopyFrameDataToArray((uint)frameData.Length, frameDataPtr);
                Marshal.Copy(frameDataPtr, frameData, 0, frameData.Length);
            }
            catch { }
            finally
            {
                if (frameDataPtr != IntPtr.Zero)
                    Marshal.FreeCoTaskMem(frameDataPtr);
            }
        }
        public void CopyFrameDataToIntPtr(IntPtr frameData, uint size)
        {
            try { origin.CopyFrameDataToArray(size, frameData); }
            catch { }
        }
        public KinectBuffer LockAudioBuffer()
        {
            try
            {
                uint size = 0;
                IntPtr ptr = IntPtr.Zero;
                origin.AccessUnderlyingBuffer(out size, out ptr);
                return new KinectBuffer(ptr, size);
            }
            catch { }
            return null;
        }
    }

    public class AudioBodyCorrelation : BaseInterfaceWrap<IAudioBodyCorrelation>
    {
        public AudioBodyCorrelation() : base() { }
        internal AudioBodyCorrelation(IAudioBodyCorrelation arg) : base(arg) { }
        public ulong BodyTrackingId
        {
            get { return GetMember<ulong>("BodyTrackingId"); }
        }
    }

    public class AudioBeam : BaseInterfaceWrap<IAudioBeam>
    {
        public AudioBeam() : base() { }
        internal AudioBeam(IAudioBeam arg) : base(arg) { }
        public AudioBeamMode AudioBeamMode
        {
            get { return GetMember<AudioBeamMode>("AudioBeamMode"); }
            set { PutMember<AudioBeamMode>("AudioBeamMode", value); }
        }
        public AudioSource AudioSource
        {
            get { return new AudioSource(GetMember<IAudioSource>("AudioSource")); }
        }
        public float BeamAangle
        {
            get { return GetMember<float>("BeamAangle"); }
        }
        public float BeamAngleConfidence
        {
            get { return GetMember<float>("BeamAngleConfidence"); }
        }
        public TimeSpan RelativeTime
        {
            get { return GetTimeSpan("RelativeTime"); }
        }
        public Stream OpenInputStream()
        {
            try { return new Stream(origin.OpenInputStream()); }
            catch { }
            return null;
        }
    }

    public class Stream : System.IO.Stream
    {
        private IStream stream;
        private IntPtr tmp;

        public Stream(IStream stream)
        {
            if (stream == null)
                throw new NullReferenceException("IStream");
            this.stream = stream;
            tmp = Marshal.AllocCoTaskMem(8);

        }
        ~Stream()
        {
            Marshal.FreeCoTaskMem(tmp);
            if (stream != null)
                Marshal.ReleaseComObject(stream);
        }
        public override bool CanRead { get { return true; } }
        public override bool CanSeek { get { return true; } }
        public override bool CanWrite { get { return true; } }
        public override void Flush()
        {
            stream.Commit(0);
        }
        public override long Length
        {
            get
            {
                System.Runtime.InteropServices.ComTypes.STATSTG stat;
                stream.Stat(out stat, 1);
                return stat.cbSize;
            }
        }
        public override long Position
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }
        public override int Read(byte[] buffer, int offset, int count)
        {
            byte[] buf = null;
            if (offset == 0)
                buf = buffer;
            else if (offset > 0)
                buf = new byte[count];
            else
                new NotImplementedException();
            stream.Read(buf, count, tmp);
            int length = Marshal.ReadInt32(tmp);
            if (offset > 0 && length > 0)
                Array.Copy(buf, 0, buffer, offset, length);
            return length;
        }
        public override long Seek(long offset, System.IO.SeekOrigin origin)
        {
            stream.Seek(offset, (int)origin, tmp);
            return Marshal.ReadInt64(tmp);
        }
        public override void SetLength(long value)
        {
            stream.SetSize(value);
        }
        public override void Write(byte[] buffer, int offset, int count)
        {
            if (offset != 0) throw new NotImplementedException();
            stream.Write(buffer, count, IntPtr.Zero);
        }
    }
}